<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title>《长恨歌》 - Even - A super concise theme for Hugo</title>
  <meta name="renderer" content="webkit" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>

<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />

<meta name="theme-color" content="#f8f5ec" />
<meta name="msapplication-navbutton-color" content="#f8f5ec">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="#f8f5ec">


<meta name="author" content="Wikipedia" /><meta name="description" content="从 Memory Reordering 说起 下面这段代码会有怎样的输出 1 2 3 4 5 6 7 8 9 var x, y int go func() { x = 1 // A1 fmt.Print(&amp;#34;y:&amp;#34;, y, &amp;#34; &amp;#34;) // A2 }() go func() { y = 1 // B1 fmt.Print(&amp;#34;x:&amp;#34;, x, &amp;#34; &amp;#34;) // B2 }() 显而易见的几种结果" /><meta name="keywords" content="Hugo, theme, even" />






<meta name="generator" content="Hugo 0.83.1 with theme even" />


<link rel="canonical" href="http://localhost:1313/post/cpu/cpu%E5%86%85%E5%AD%98%E9%87%8D%E6%8E%92/" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/manifest.json">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">



<link href="/sass/main.min.f92fd13721ddf72129410fd8250e73152cc6f2438082b6c0208dc24ee7c13fc4.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.1.20/dist/jquery.fancybox.min.css" integrity="sha256-7TyXnr2YU040zfSP+rEcz29ggW4j56/ujTPwjMzyqFY=" crossorigin="anonymous">


<meta property="og:title" content="《长恨歌》" />
<meta property="og:description" content="从 Memory Reordering 说起 下面这段代码会有怎样的输出 1 2 3 4 5 6 7 8 9 var x, y int go func() { x = 1 // A1 fmt.Print(&#34;y:&#34;, y, &#34; &#34;) // A2 }() go func() { y = 1 // B1 fmt.Print(&#34;x:&#34;, x, &#34; &#34;) // B2 }() 显而易见的几种结果" />
<meta property="og:type" content="article" />
<meta property="og:url" content="http://localhost:1313/post/cpu/cpu%E5%86%85%E5%AD%98%E9%87%8D%E6%8E%92/" /><meta property="article:section" content="post" />
<meta property="article:published_time" content="2017-08-30T01:37:56&#43;08:00" />
<meta property="article:modified_time" content="2017-08-30T01:37:56&#43;08:00" />

<meta itemprop="name" content="《长恨歌》">
<meta itemprop="description" content="从 Memory Reordering 说起 下面这段代码会有怎样的输出 1 2 3 4 5 6 7 8 9 var x, y int go func() { x = 1 // A1 fmt.Print(&#34;y:&#34;, y, &#34; &#34;) // A2 }() go func() { y = 1 // B1 fmt.Print(&#34;x:&#34;, x, &#34; &#34;) // B2 }() 显而易见的几种结果"><meta itemprop="datePublished" content="2017-08-30T01:37:56&#43;08:00" />
<meta itemprop="dateModified" content="2017-08-30T01:37:56&#43;08:00" />
<meta itemprop="wordCount" content="1904">
<meta itemprop="keywords" content="preview,中文,tag-1," /><meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="《长恨歌》"/>
<meta name="twitter:description" content="从 Memory Reordering 说起 下面这段代码会有怎样的输出 1 2 3 4 5 6 7 8 9 var x, y int go func() { x = 1 // A1 fmt.Print(&#34;y:&#34;, y, &#34; &#34;) // A2 }() go func() { y = 1 // B1 fmt.Print(&#34;x:&#34;, x, &#34; &#34;) // B2 }() 显而易见的几种结果"/>

<!--[if lte IE 9]>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/classlist/1.1.20170427/classList.min.js"></script>
<![endif]-->

<!--[if lt IE 9]>
  <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
<![endif]-->

</head>
<body>
  <div id="mobile-navbar" class="mobile-navbar">
  <div class="mobile-header-logo">
    <a href="/" class="logo">Even</a>
  </div>
  <div class="mobile-navbar-icon">
    <span></span>
    <span></span>
    <span></span>
  </div>
</div>
<nav id="mobile-menu" class="mobile-menu slideout-menu">
  <ul class="mobile-menu-list">
    <a href="/">
        <li class="mobile-menu-item">Home</li>
      </a><a href="/post/">
        <li class="mobile-menu-item">Archives</li>
      </a><a href="/tags/">
        <li class="mobile-menu-item">Tags</li>
      </a><a href="/categories/">
        <li class="mobile-menu-item">Categories</li>
      </a>
  </ul>

  


</nav>

  <div class="container" id="mobile-panel">
    <header id="header" class="header">
        <div class="logo-wrapper">
  <a href="/" class="logo">Even</a>
</div>





<nav class="site-navbar">
  <ul id="menu" class="menu">
    <li class="menu-item">
        <a class="menu-item-link" href="/">Home</a>
      </li><li class="menu-item">
        <a class="menu-item-link" href="/post/">Archives</a>
      </li><li class="menu-item">
        <a class="menu-item-link" href="/tags/">Tags</a>
      </li><li class="menu-item">
        <a class="menu-item-link" href="/categories/">Categories</a>
      </li>
  </ul>
</nav>

    </header>

    <main id="main" class="main">
      <div class="content-wrapper">
        <div id="content" class="content">
          <article class="post">
    
    <header class="post-header">
      <h1 class="post-title">《长恨歌》</h1>

      <div class="post-meta">
        <span class="post-time"> 2017-08-30 </span>
        <div class="post-category">
            <a href="/categories/%E4%B8%AD%E6%96%87/"> 中文 </a>
            </div>
        
      </div>
    </header>

    <div class="post-toc" id="post-toc">
  <h2 class="post-toc-title">Contents</h2>
  <div class="post-toc-content always-active">
    <nav id="TableOfContents">
  <ul>
    <li><a href="#从-memory-reordering-说起">从 Memory Reordering 说起</a>
      <ul>
        <li><a href="#什么是内存重排">什么是内存重排</a></li>
        <li><a href="#为什么会发生内存重排">为什么会发生内存重排</a>
          <ul>
            <li><a href="#编译器重排">编译器重排</a></li>
            <li><a href="#cpu-重排">CPU 重排</a></li>
          </ul>
        </li>
        <li><a href="#内存重排的目的">内存重排的目的</a></li>
        <li><a href="#当我们需要顺序的时候我们在讨论些什么">当我们需要顺序的时候,我们在讨论些什么</a>
          <ul>
            <li><a href="#memory-barrier">memory barrier</a></li>
            <li><a href="#atomic">atomic</a></li>
            <li><a href="#lock">lock</a></li>
            <li><a href="#你的系统在锁上出问题的最明显特征">你的系统在锁上出问题的最明显特征</a></li>
          </ul>
        </li>
        <li><a href="#cache-contention">cache contention</a>
          <ul>
            <li><a href="#true-sharing">true sharing</a></li>
            <li><a href="#false-sharing">false sharing</a></li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
</nav>
  </div>
</div>
    <div class="post-content">
      <h1 id="从-memory-reordering-说起">从 Memory Reordering 说起</h1>
<p>下面这段代码会有怎样的输出</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-c" data-lang="c"><span class="n">var</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="kt">int</span>
<span class="n">go</span> <span class="n">func</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">x</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1">// A1
</span><span class="c1"></span>    <span class="n">fmt</span><span class="p">.</span><span class="n">Print</span><span class="p">(</span><span class="s">&#34;y:&#34;</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="s">&#34; &#34;</span><span class="p">)</span> <span class="c1">// A2
</span><span class="c1"></span><span class="p">}()</span>
<span class="n">go</span> <span class="n">func</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">y</span> <span class="o">=</span> <span class="mi">1</span>                   <span class="c1">// B1
</span><span class="c1"></span>    <span class="n">fmt</span><span class="p">.</span><span class="n">Print</span><span class="p">(</span><span class="s">&#34;x:&#34;</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="s">&#34; &#34;</span><span class="p">)</span> <span class="c1">// B2
</span><span class="c1"></span><span class="p">}()</span>
</code></pre></td></tr></table>
</div>
</div><p>显而易见的几种结果:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-c" data-lang="c"><span class="nl">y</span><span class="p">:</span><span class="mi">0</span> <span class="nl">x</span><span class="p">:</span><span class="mi">1</span>
<span class="nl">x</span><span class="p">:</span><span class="mi">0</span> <span class="nl">y</span><span class="p">:</span><span class="mi">1</span>
<span class="nl">x</span><span class="p">:</span><span class="mi">1</span> <span class="nl">y</span><span class="p">:</span><span class="mi">1</span>
<span class="nl">y</span><span class="p">:</span><span class="mi">1</span> <span class="nl">x</span><span class="p">:</span><span class="mi">1</span>
</code></pre></td></tr></table>
</div>
</div><p>令人意外的结果</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-c" data-lang="c"><span class="nl">x</span><span class="p">:</span><span class="mi">0</span> <span class="nl">y</span><span class="p">:</span><span class="mi">0</span>
<span class="nl">y</span><span class="p">:</span><span class="mi">0</span> <span class="nl">x</span><span class="p">:</span><span class="mi">0</span>
</code></pre></td></tr></table>
</div>
</div><p>这种令人意外的结果被称为内存重排： Memory Reordering</p>
<h2 id="什么是内存重排">什么是内存重排</h2>
<blockquote>
<p>内存重排指的是内存的读/写指令重排。</p>
</blockquote>
<p>— Xargin</p>
<p>软件或硬件系统可以根据其对代码的分析结果,一定程度上打乱代码的执行顺序，以达到其不可告人的目的。</p>
<h2 id="为什么会发生内存重排">为什么会发生内存重排</h2>
<h3 id="编译器重排">编译器重排</h3>
<p>snippet 1</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-python" data-lang="python"><span class="n">X</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">):</span>
    <span class="n">X</span> <span class="o">=</span> <span class="mi">1</span>
    <span class="k">print</span> <span class="n">X</span>
</code></pre></td></tr></table>
</div>
</div><p>snippet 2</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-python" data-lang="python"><span class="n">X</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">):</span>
    <span class="k">print</span> <span class="n">X</span>
</code></pre></td></tr></table>
</div>
</div><p><a href="https://cch123.github.io/ooo/#snippet1">snippet 1</a> 和 <a href="https://cch123.github.io/ooo/#snippet2">snippet 2</a> 是等价的。</p>
<p>如果这时候，假设有 Processor 2 同时在执行一条指令：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-python" data-lang="python"><span class="n">X</span> <span class="o">=</span> <span class="mi">0</span>
</code></pre></td></tr></table>
</div>
</div><p>P2 中的指令和 <a href="https://cch123.github.io/ooo/#snippet1">snippet 1</a> 交错执行时，可能产生的结果是：111101111..</p>
<p>P2 中的指令和 <a href="https://cch123.github.io/ooo/#snippet2">snippet 2</a> 交错执行时，可能产生的结果是：11100000…</p>
<p><strong>有人说这个例子不够有说服力</strong>，我们看看参考资料中的另一个例子:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-c" data-lang="c"><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">;</span>
<span class="kt">int</span> <span class="nf">foo</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">a</span> <span class="o">=</span> <span class="n">b</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
    <span class="n">b</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></td></tr></table>
</div>
</div><p>输出汇编:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-c" data-lang="c"><span class="n">mov</span> <span class="n">eax</span><span class="p">,</span> <span class="n">DWORD</span> <span class="n">PTR</span> <span class="n">b</span><span class="p">[</span><span class="n">rip</span><span class="p">]</span>
<span class="n">add</span> <span class="n">eax</span><span class="p">,</span> <span class="mi">1</span>
<span class="n">mov</span> <span class="n">DWORD</span> <span class="n">PTR</span> <span class="n">a</span><span class="p">[</span><span class="n">rip</span><span class="p">],</span> <span class="n">eax</span>    <span class="c1">// --&gt; store to a
</span><span class="c1"></span><span class="n">mov</span> <span class="n">DWORD</span> <span class="n">PTR</span> <span class="n">b</span><span class="p">[</span><span class="n">rip</span><span class="p">],</span> <span class="mi">0</span>      <span class="c1">// --&gt; store to b
</span></code></pre></td></tr></table>
</div>
</div><p>开启 O2 优化后，输出汇编:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-c" data-lang="c"><span class="n">mov</span> <span class="n">eax</span><span class="p">,</span> <span class="n">DWORD</span> <span class="n">PTR</span> <span class="n">b</span><span class="p">[</span><span class="n">rip</span><span class="p">]</span>
<span class="n">mov</span> <span class="n">DWORD</span> <span class="n">PTR</span> <span class="n">b</span><span class="p">[</span><span class="n">rip</span><span class="p">],</span> <span class="mi">0</span>      <span class="c1">// --&gt; store to b
</span><span class="c1"></span><span class="n">add</span> <span class="n">eax</span><span class="p">,</span> <span class="mi">1</span>
<span class="n">mov</span> <span class="n">DWORD</span> <span class="n">PTR</span> <span class="n">a</span><span class="p">[</span><span class="n">rip</span><span class="p">],</span> <span class="n">eax</span>    <span class="c1">// --&gt; store to a
</span></code></pre></td></tr></table>
</div>
</div><p>给 a 和 b 的赋值顺序被修改了，可见 compiler 也是可能会修改赋值的顺序的。</p>
<table>
<thead>
<tr>
<th></th>
<th>在多核心场景下,没有办法轻易地判断两段程序是“等价”的。</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<h3 id="cpu-重排">CPU 重排</h3>
<h4 id="litmus-验证">litmus 验证</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-c" data-lang="c"><span class="n">cat</span> <span class="n">sb</span><span class="p">.</span><span class="n">litmus</span>

<span class="n">X86</span> <span class="n">SB</span>
<span class="p">{</span> <span class="n">x</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">y</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="p">}</span>
 <span class="n">P0</span>          <span class="o">|</span> <span class="n">P1</span>          <span class="p">;</span>
 <span class="n">MOV</span> <span class="p">[</span><span class="n">x</span><span class="p">],</span><span class="err">$</span><span class="mi">1</span>  <span class="o">|</span> <span class="n">MOV</span> <span class="p">[</span><span class="n">y</span><span class="p">],</span><span class="err">$</span><span class="mi">1</span>  <span class="p">;</span>
 <span class="n">MOV</span> <span class="n">EAX</span><span class="p">,[</span><span class="n">y</span><span class="p">]</span> <span class="o">|</span> <span class="n">MOV</span> <span class="n">EAX</span><span class="p">,[</span><span class="n">x</span><span class="p">]</span> <span class="p">;</span>
<span class="n">locations</span> <span class="p">[</span><span class="n">x</span><span class="p">;</span><span class="n">y</span><span class="p">;]</span>
<span class="n">exists</span> <span class="p">(</span><span class="mi">0</span><span class="o">:</span><span class="n">EAX</span><span class="o">=</span><span class="mi">0</span> <span class="o">/</span><span class="err">\</span> <span class="mi">1</span><span class="o">:</span><span class="n">EAX</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
</code></pre></td></tr></table>
</div>
</div><p>⇒</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-c" data-lang="c"><span class="o">~</span> <span class="err">❯❯❯</span> <span class="n">bin</span><span class="o">/</span><span class="n">litmus7</span> <span class="p">.</span><span class="o">/</span><span class="n">sb</span><span class="p">.</span><span class="n">litmus</span>
<span class="o">%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>
<span class="o">%</span> <span class="n">Results</span> <span class="k">for</span> <span class="p">.</span><span class="o">/</span><span class="n">sb</span><span class="p">.</span><span class="n">litmus</span> <span class="o">%</span>
<span class="o">%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>
<span class="n">X86</span> <span class="n">SB</span>

<span class="p">{</span><span class="n">x</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">y</span><span class="o">=</span><span class="mi">0</span><span class="p">;}</span>

 <span class="n">P0</span>          <span class="o">|</span> <span class="n">P1</span>          <span class="p">;</span>
 <span class="n">MOV</span> <span class="p">[</span><span class="n">x</span><span class="p">],</span><span class="err">$</span><span class="mi">1</span>  <span class="o">|</span> <span class="n">MOV</span> <span class="p">[</span><span class="n">y</span><span class="p">],</span><span class="err">$</span><span class="mi">1</span>  <span class="p">;</span>
 <span class="n">MOV</span> <span class="n">EAX</span><span class="p">,[</span><span class="n">y</span><span class="p">]</span> <span class="o">|</span> <span class="n">MOV</span> <span class="n">EAX</span><span class="p">,[</span><span class="n">x</span><span class="p">]</span> <span class="p">;</span>

<span class="n">locations</span> <span class="p">[</span><span class="n">x</span><span class="p">;</span> <span class="n">y</span><span class="p">;]</span>
<span class="n">exists</span> <span class="p">(</span><span class="mi">0</span><span class="o">:</span><span class="n">EAX</span><span class="o">=</span><span class="mi">0</span> <span class="o">/</span><span class="err">\</span> <span class="mi">1</span><span class="o">:</span><span class="n">EAX</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
<span class="n">Generated</span> <span class="n">assembler</span>
	<span class="cp">##START _litmus_P0
</span><span class="cp"></span>	<span class="n">movl</span>	<span class="err">$</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">4</span><span class="p">(</span><span class="o">%</span><span class="n">rbx</span><span class="p">,</span><span class="o">%</span><span class="n">rcx</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span>
	<span class="n">movl</span>	<span class="o">-</span><span class="mi">4</span><span class="p">(</span><span class="o">%</span><span class="n">rsi</span><span class="p">,</span><span class="o">%</span><span class="n">rcx</span><span class="p">,</span><span class="mi">4</span><span class="p">),</span> <span class="o">%</span><span class="n">eax</span>
	<span class="cp">##START _litmus_P1
</span><span class="cp"></span>	<span class="n">movl</span>	<span class="err">$</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">4</span><span class="p">(</span><span class="o">%</span><span class="n">rsi</span><span class="p">,</span><span class="o">%</span><span class="n">rcx</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span>
	<span class="n">movl</span>	<span class="o">-</span><span class="mi">4</span><span class="p">(</span><span class="o">%</span><span class="n">rbx</span><span class="p">,</span><span class="o">%</span><span class="n">rcx</span><span class="p">,</span><span class="mi">4</span><span class="p">),</span> <span class="o">%</span><span class="n">eax</span>

<span class="n">Test</span> <span class="n">SB</span> <span class="n">Allowed</span>
<span class="n">Histogram</span> <span class="p">(</span><span class="mi">4</span> <span class="n">states</span><span class="p">)</span>
<span class="mi">96</span>    <span class="o">*&gt;</span><span class="mi">0</span><span class="o">:</span><span class="n">EAX</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="mi">1</span><span class="o">:</span><span class="n">EAX</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">x</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span> <span class="n">y</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span>
<span class="mi">499878</span><span class="o">:&gt;</span><span class="mi">0</span><span class="o">:</span><span class="n">EAX</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span> <span class="mi">1</span><span class="o">:</span><span class="n">EAX</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">x</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span> <span class="n">y</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span>
<span class="mi">499862</span><span class="o">:&gt;</span><span class="mi">0</span><span class="o">:</span><span class="n">EAX</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="mi">1</span><span class="o">:</span><span class="n">EAX</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span> <span class="n">x</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span> <span class="n">y</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span>
<span class="mi">164</span>   <span class="o">:&gt;</span><span class="mi">0</span><span class="o">:</span><span class="n">EAX</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span> <span class="mi">1</span><span class="o">:</span><span class="n">EAX</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span> <span class="n">x</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span> <span class="n">y</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span>
<span class="n">Ok</span>

<span class="n">Witnesses</span>
<span class="nl">Positive</span><span class="p">:</span> <span class="mi">96</span><span class="p">,</span> <span class="nl">Negative</span><span class="p">:</span> <span class="mi">999904</span>
<span class="n">Condition</span> <span class="n">exists</span> <span class="p">(</span><span class="mi">0</span><span class="o">:</span><span class="n">EAX</span><span class="o">=</span><span class="mi">0</span> <span class="o">/</span><span class="err">\</span> <span class="mi">1</span><span class="o">:</span><span class="n">EAX</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span> <span class="n">is</span> <span class="n">validated</span>
<span class="n">Hash</span><span class="o">=</span><span class="mi">2</span><span class="n">d53e83cd627ba17ab11c875525e078b</span>
<span class="n">Observation</span> <span class="n">SB</span> <span class="n">Sometimes</span> <span class="mi">96</span> <span class="mi">999904</span>
<span class="n">Time</span> <span class="n">SB</span> <span class="mf">0.11</span>
</code></pre></td></tr></table>
</div>
</div><h4 id="cpu-架构">CPU 架构</h4>
<p><img src="/Users/fengbinshi/Documents/%E7%AC%94%E8%AE%B0/images/cpu-arch.png" alt="cpu arch.png"></p>
<p>Figure 1. CPU Architecture</p>
<p><img src="/Users/fengbinshi/Documents/%E7%AC%94%E8%AE%B0/images/wb.png" alt="wb.png"></p>
<p>Figure 2. Store Buffer</p>
<p>这里的 Invalidate Queue 实际上稍微有一些简化,真实世界的 CPU 在做 invalidate 操作时还是挺麻烦的:</p>
<p><img src="/Users/fengbinshi/Documents/%E7%AC%94%E8%AE%B0/images/mesi.jpg" alt="mesi.jpg"></p>
<p>Figure 3. MESI Protocol</p>
<p><img src="/Users/fengbinshi/Documents/%E7%AC%94%E8%AE%B0/images/L1.png" alt="L1.png"></p>
<p>Figure 4. CPU Cache Structure</p>
<h2 id="内存重排的目的">内存重排的目的</h2>
<table>
<thead>
<tr>
<th></th>
<th>当然是为了优化啊。这还用说吗</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<ul>
<li>减少读写等待导致的性能降低</li>
<li>最大化提高 CPU 利用率。</li>
</ul>
<h2 id="当我们需要顺序的时候我们在讨论些什么">当我们需要顺序的时候,我们在讨论些什么</h2>
<h3 id="memory-barrier">memory barrier</h3>
<blockquote>
<p>A memory barrier, also known as a membar, memory fence or fence instruction, is a type of barrier instruction that causes a central processing unit (CPU) or compiler to enforce an ordering constraint on memory operations issued before and after the barrier instruction.</p>
</blockquote>
<p>— wikipedia</p>
<p>有了 memory barrier，才能实现应用层的各种同步原语。如 atomic，而 atomic 又是各种更上层 lock 的基础。</p>
<h3 id="atomic">atomic</h3>
<blockquote>
<p>On x86, it will turn into a lock prefixed assembly instruction, like LOCK XADD. Being a single instruction, it is non-interruptible. As an added &ldquo;feature&rdquo;, the lock prefix results in a full memory barrier</p>
</blockquote>
<p>— Stackoverflow</p>
<blockquote>
<p>&ldquo;…locked operations serialize all outstanding load and store operations (that is, wait for them to complete).&rdquo; …&ldquo;Locked operations are atomic with respect to all other memory operations and all externally visible events. Only instruction fetch and page table accesses can pass locked instructions. Locked instructions can be used to synchronize data written by one processor and read by another processor.&rdquo; -</p>
</blockquote>
<p>— Intel® 64 and IA-32 Architectures Software Developer’s ManualChapter 8.1.2.</p>
<h4 id="atomic-应用示例双buffer">atomic 应用示例：双buffer</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-c" data-lang="c"><span class="n">var</span> <span class="n">doublebuffer</span> <span class="k">struct</span> <span class="p">{</span>
    <span class="n">buffer</span> <span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="n">option</span>
    <span class="n">idx</span>    <span class="n">int64</span>
<span class="p">}</span>

<span class="n">atomic</span><span class="p">.</span><span class="n">Load</span><span class="p">(</span><span class="o">&amp;</span><span class="n">doublebuffer</span><span class="p">.</span><span class="n">idx</span><span class="p">)</span>

<span class="n">atomic</span><span class="p">.</span><span class="n">CompareAndSwapInt64</span><span class="p">(</span><span class="o">&amp;</span><span class="n">doublebuffer</span><span class="p">.</span><span class="n">idx</span><span class="p">,</span> <span class="n">doublebuffer</span><span class="p">.</span><span class="n">idx</span><span class="p">,</span> <span class="mi">1</span><span class="o">-</span><span class="n">doublebuffer</span><span class="p">.</span><span class="n">idx</span><span class="p">)</span>
</code></pre></td></tr></table>
</div>
</div><p>option 可以是任意的自定义数据结构。</p>
<h3 id="lock">lock</h3>
<p>概念和用法就不讲了，你们应该都用过。没有免费的午餐，有锁冲突就会大幅度降低性能。</p>
<p>为了减小对性能的影响，锁应尽量减小粒度，并且不在互斥区内放入耗时操作，但是总是有一些悲伤的故事:</p>
<h4 id="syncpool-中的锁">sync.Pool 中的锁</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-c" data-lang="c"><span class="n">var</span> <span class="p">(</span>
	<span class="n">allPoolsMu</span> <span class="n">Mutex</span>
	<span class="n">allPools</span>   <span class="p">[]</span><span class="o">*</span><span class="n">Pool</span>
<span class="p">)</span>

<span class="n">func</span> <span class="p">(</span><span class="n">p</span> <span class="o">*</span><span class="n">Pool</span><span class="p">)</span> <span class="n">pinSlow</span><span class="p">()</span> <span class="o">*</span><span class="n">poolLocal</span> <span class="p">{</span>
	<span class="n">allPoolsMu</span><span class="p">.</span><span class="n">Lock</span><span class="p">()</span>
	<span class="n">defer</span> <span class="n">allPoolsMu</span><span class="p">.</span><span class="n">Unlock</span><span class="p">()</span>
	<span class="nl">pid</span> <span class="p">:</span><span class="o">=</span> <span class="n">runtime_procPin</span><span class="p">()</span>

	<span class="k">if</span> <span class="n">p</span><span class="p">.</span><span class="n">local</span> <span class="o">==</span> <span class="n">nil</span> <span class="p">{</span>
		<span class="n">allPools</span> <span class="o">=</span> <span class="n">append</span><span class="p">(</span><span class="n">allPools</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
	<span class="p">}</span>

    <span class="c1">//........
</span><span class="c1"></span>	<span class="k">return</span> <span class="o">&amp;</span><span class="n">local</span><span class="p">[</span><span class="n">pid</span><span class="p">]</span>
<span class="p">}</span>
</code></pre></td></tr></table>
</div>
</div><h4 id="udp-writeto-的锁">udp WriteTo 的锁</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-c" data-lang="c"><span class="n">func</span> <span class="p">(</span><span class="n">fd</span> <span class="o">*</span><span class="n">FD</span><span class="p">)</span> <span class="n">WriteTo</span><span class="p">(</span><span class="n">p</span> <span class="p">[]</span><span class="n">byte</span><span class="p">,</span> <span class="n">sa</span> <span class="n">syscall</span><span class="p">.</span><span class="n">Sockaddr</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span><span class="p">,</span> <span class="n">error</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">if</span> <span class="nl">err</span> <span class="p">:</span><span class="o">=</span> <span class="n">fd</span><span class="p">.</span><span class="n">writeLock</span><span class="p">();</span> <span class="n">err</span> <span class="o">!=</span> <span class="n">nil</span> <span class="p">{</span>
		<span class="k">return</span> <span class="mi">0</span><span class="p">,</span> <span class="n">err</span>
	<span class="p">}</span>
	<span class="n">defer</span> <span class="n">fd</span><span class="p">.</span><span class="n">writeUnlock</span><span class="p">()</span>
	<span class="k">if</span> <span class="nl">err</span> <span class="p">:</span><span class="o">=</span> <span class="n">fd</span><span class="p">.</span><span class="n">pd</span><span class="p">.</span><span class="n">prepareWrite</span><span class="p">(</span><span class="n">fd</span><span class="p">.</span><span class="n">isFile</span><span class="p">);</span> <span class="n">err</span> <span class="o">!=</span> <span class="n">nil</span> <span class="p">{</span>
		<span class="k">return</span> <span class="mi">0</span><span class="p">,</span> <span class="n">err</span>
	<span class="p">}</span>
	<span class="k">for</span> <span class="p">{</span>
		<span class="nl">err</span> <span class="p">:</span><span class="o">=</span> <span class="n">syscall</span><span class="p">.</span><span class="n">Sendto</span><span class="p">(</span><span class="n">fd</span><span class="p">.</span><span class="n">Sysfd</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">sa</span><span class="p">)</span>
		<span class="k">if</span> <span class="n">err</span> <span class="o">==</span> <span class="n">syscall</span><span class="p">.</span><span class="n">EAGAIN</span> <span class="o">&amp;&amp;</span> <span class="n">fd</span><span class="p">.</span><span class="n">pd</span><span class="p">.</span><span class="n">pollable</span><span class="p">()</span> <span class="p">{</span>
			<span class="k">if</span> <span class="n">err</span> <span class="o">=</span> <span class="n">fd</span><span class="p">.</span><span class="n">pd</span><span class="p">.</span><span class="n">waitWrite</span><span class="p">(</span><span class="n">fd</span><span class="p">.</span><span class="n">isFile</span><span class="p">);</span> <span class="n">err</span> <span class="o">==</span> <span class="n">nil</span> <span class="p">{</span>
				<span class="k">continue</span>
			<span class="p">}</span>
		<span class="p">}</span>
		<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="n">nil</span> <span class="p">{</span>
			<span class="k">return</span> <span class="mi">0</span><span class="p">,</span> <span class="n">err</span>
		<span class="p">}</span>
		<span class="k">return</span> <span class="n">len</span><span class="p">(</span><span class="n">p</span><span class="p">),</span> <span class="n">nil</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></td></tr></table>
</div>
</div><h4 id="tcp-transport-上也有锁">tcp transport 上也有锁！</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-c" data-lang="c"><span class="n">type</span> <span class="n">Transport</span> <span class="k">struct</span> <span class="p">{</span>
	<span class="n">idleMu</span>     <span class="n">sync</span><span class="p">.</span><span class="n">Mutex</span>
	<span class="n">wantIdle</span>   <span class="kt">bool</span>                                <span class="c1">// user has requested to close all idle conns
</span><span class="c1"></span>	<span class="n">idleConn</span>   <span class="n">map</span><span class="p">[</span><span class="n">connectMethodKey</span><span class="p">][]</span><span class="o">*</span><span class="n">persistConn</span> <span class="c1">// most recently used at end
</span><span class="c1"></span>	<span class="n">idleConnCh</span> <span class="n">map</span><span class="p">[</span><span class="n">connectMethodKey</span><span class="p">]</span><span class="n">chan</span> <span class="o">*</span><span class="n">persistConn</span>
	<span class="n">idleLRU</span>    <span class="n">connLRU</span>

	<span class="n">reqMu</span>       <span class="n">sync</span><span class="p">.</span><span class="n">Mutex</span>
	<span class="n">reqCanceler</span> <span class="n">map</span><span class="p">[</span><span class="o">*</span><span class="n">Request</span><span class="p">]</span><span class="n">func</span><span class="p">(</span><span class="n">error</span><span class="p">)</span>

	<span class="n">altMu</span>    <span class="n">sync</span><span class="p">.</span><span class="n">Mutex</span>   <span class="c1">// guards changing altProto only
</span><span class="c1"></span>	<span class="n">altProto</span> <span class="n">atomic</span><span class="p">.</span><span class="n">Value</span> <span class="c1">// of nil or map[string]RoundTripper, key is URI scheme
</span><span class="c1"></span>
	<span class="n">connCountMu</span>          <span class="n">sync</span><span class="p">.</span><span class="n">Mutex</span>
	<span class="n">connPerHostCount</span>     <span class="n">map</span><span class="p">[</span><span class="n">connectMethodKey</span><span class="p">]</span><span class="kt">int</span>
	<span class="n">connPerHostAvailable</span> <span class="n">map</span><span class="p">[</span><span class="n">connectMethodKey</span><span class="p">]</span><span class="n">chan</span> <span class="k">struct</span><span class="p">{}</span>

    <span class="c1">//......
</span></code></pre></td></tr></table>
</div>
</div><p>会不会碰上瓶颈要随缘。</p>
<h3 id="你的系统在锁上出问题的最明显特征">你的系统在锁上出问题的最明显特征</h3>
<ul>
<li>压测过不了几千级别的 QPS(丢人！</li>
<li>Goroutine 一开始很稳定，超过一定 QPS 之后暴涨</li>
<li>可以通过压测方便地发现问题。</li>
</ul>
<p>lock contention 的本质问题是需要进入互斥区的 g 需要等待独占 g 退出后才能进入互斥区，并行 → 串行</p>
<h2 id="cache-contention">cache contention</h2>
<p>cache contention 那也是 contention，使用 atomic，或者 false sharing 就会导致 cache contention。</p>
<p>atomic 操作可以理解成 “true sharing”。</p>
<p>症状：在核心数增多时，单次操作的成本上升，导致程序整体性能下降。</p>
<h3 id="true-sharing">true sharing</h3>
<p>例子:</p>
<p>RWMutex 的 RLock:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-c" data-lang="c"><span class="n">func</span> <span class="p">(</span><span class="n">rw</span> <span class="o">*</span><span class="n">RWMutex</span><span class="p">)</span> <span class="n">RLock</span><span class="p">()</span> <span class="p">{</span>
    <span class="c1">// ....
</span><span class="c1"></span>	<span class="k">if</span> <span class="n">atomic</span><span class="p">.</span><span class="n">AddInt32</span><span class="p">(</span><span class="o">&amp;</span><span class="n">rw</span><span class="p">.</span><span class="n">readerCount</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="p">{</span>
		<span class="c1">// A writer is pending, wait for it.
</span><span class="c1"></span>		<span class="n">runtime_SemacquireMutex</span><span class="p">(</span><span class="o">&amp;</span><span class="n">rw</span><span class="p">.</span><span class="n">readerSem</span><span class="p">,</span> <span class="nb">false</span><span class="p">)</span>
	<span class="p">}</span>

    <span class="c1">// else 获取 RLock 成功
</span><span class="c1"></span>    <span class="c1">// ....
</span><span class="c1"></span><span class="p">}</span>
</code></pre></td></tr></table>
</div>
</div><p>true sharing 带来的问题：</p>
<blockquote>
<p>sync: RWMutex scales poorly with CPU count</p>
</blockquote>
<p>— issue 17973</p>
<p>至今还没有解决这个问题，如果解决了的话，根本不需要 sync.Map 出现了。</p>
<h3 id="false-sharing">false sharing</h3>
<p>runtime/sema.go</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-c" data-lang="c"><span class="n">var</span> <span class="n">semtable</span> <span class="p">[</span><span class="n">semTabSize</span><span class="p">]</span><span class="k">struct</span> <span class="p">{</span>
	<span class="n">root</span> <span class="n">semaRoot</span>
	<span class="n">pad</span>  <span class="p">[</span><span class="n">cpu</span><span class="p">.</span><span class="n">CacheLinePadSize</span> <span class="o">-</span> <span class="n">unsafe</span><span class="p">.</span><span class="n">Sizeof</span><span class="p">(</span><span class="n">semaRoot</span><span class="p">{})]</span><span class="n">byte</span>
<span class="p">}</span>
</code></pre></td></tr></table>
</div>
</div><p>runtime/time.go</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-c" data-lang="c"><span class="n">var</span> <span class="n">timers</span> <span class="p">[</span><span class="n">timersLen</span><span class="p">]</span><span class="k">struct</span> <span class="p">{</span>
	<span class="n">timersBucket</span>

	<span class="c1">// The padding should eliminate false sharing
</span><span class="c1"></span>	<span class="c1">// between timersBucket values.
</span><span class="c1"></span>	<span class="n">pad</span> <span class="p">[</span><span class="n">cpu</span><span class="p">.</span><span class="n">CacheLinePadSize</span> <span class="o">-</span> <span class="n">unsafe</span><span class="p">.</span><span class="n">Sizeof</span><span class="p">(</span><span class="n">timersBucket</span><span class="p">{})</span><span class="o">%</span><span class="n">cpu</span><span class="p">.</span><span class="n">CacheLinePadSize</span><span class="p">]</span><span class="n">byte</span>
<span class="p">}</span>
</code></pre></td></tr></table>
</div>
</div><p>本来每个核心(在 Go 里的 GPM 中的 P 概念)独享的数据，如果发生 false sharing 了会怎么样？</p>
<p>思考题：</p>
<p>二维数组求和，横着遍历和竖着遍历哪种更快，为什么？</p>
<p>为什么 Go 官方坚持不在 sync.Map 上增加 Len 方法？</p>

    </div>

    <div class="post-copyright">
  <p class="copyright-item">
    <span class="item-title">Author</span>
    <span class="item-content">Wikipedia</span>
  </p>
  <p class="copyright-item">
    <span class="item-title">LastMod</span>
    <span class="item-content">
        2017-08-30
        
    </span>
  </p>
  
  
</div>
<footer class="post-footer">
      <div class="post-tags">
          <a href="/tags/preview/">preview</a>
          <a href="/tags/%E4%B8%AD%E6%96%87/">中文</a>
          <a href="/tags/tag-1/">tag-1</a>
          </div>
      <nav class="post-nav">
        
        <a class="next" href="/post/cpu/false-sharing/">
            <span class="next-text nav-default"></span>
            <span class="next-text nav-mobile">Next</span>
            <i class="iconfont icon-right"></i>
          </a>
      </nav>
    </footer>
  </article>
        </div>
        

  

  

      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="social-links">
      <a href="mailto:your@email.com" class="iconfont icon-email" title="email"></a>
      <a href="http://localhost:1313" class="iconfont icon-stack-overflow" title="stack-overflow"></a>
      <a href="http://localhost:1313" class="iconfont icon-twitter" title="twitter"></a>
      <a href="http://localhost:1313" class="iconfont icon-facebook" title="facebook"></a>
      <a href="http://localhost:1313" class="iconfont icon-linkedin" title="linkedin"></a>
      <a href="http://localhost:1313" class="iconfont icon-google" title="google"></a>
      <a href="http://localhost:1313" class="iconfont icon-github" title="github"></a>
      <a href="http://localhost:1313" class="iconfont icon-weibo" title="weibo"></a>
      <a href="http://localhost:1313" class="iconfont icon-zhihu" title="zhihu"></a>
      <a href="http://localhost:1313" class="iconfont icon-douban" title="douban"></a>
      <a href="http://localhost:1313" class="iconfont icon-pocket" title="pocket"></a>
      <a href="http://localhost:1313" class="iconfont icon-tumblr" title="tumblr"></a>
      <a href="http://localhost:1313" class="iconfont icon-instagram" title="instagram"></a>
      <a href="http://localhost:1313" class="iconfont icon-gitlab" title="gitlab"></a>
      <a href="http://localhost:1313" class="iconfont icon-bilibili" title="bilibili"></a>
  <a href="http://localhost:1313/index.xml" type="application/rss+xml" class="iconfont icon-rss" title="rss"></a>
</div>

<div class="copyright">
  <span class="power-by">
    Powered by <a class="hexo-link" href="https://gohugo.io">Hugo</a>
  </span>
  <span class="division">|</span>
  <span class="theme-info">
    Theme - 
    <a class="theme-link" href="https://github.com/olOwOlo/hugo-theme-even">Even</a>
  </span>

  

  <span class="copyright-year">
    &copy; 
    2017 - 
    2021<span class="heart"><i class="iconfont icon-heart"></i></span><span>olOwOlo</span>
  </span>
</div>

    </footer>

    <div class="back-to-top" id="back-to-top">
      <i class="iconfont icon-up"></i>
    </div>
  </div>
  
  <script src="https://cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/slideout@1.0.1/dist/slideout.min.js" integrity="sha256-t+zJ/g8/KXIJMjSVQdnibt4dlaDxc9zXr/9oNPeWqdg=" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.1.20/dist/jquery.fancybox.min.js" integrity="sha256-XVLffZaxoWfGUEbdzuLi7pwaUJv1cecsQJQqGLe7axY=" crossorigin="anonymous"></script>



<script type="text/javascript" src="/js/main.min.c99b103c33d1539acf3025e1913697534542c4a5aa5af0ccc20475ed2863603b.js"></script>








</body>
</html>
